<template>
  <div
      ref="reference"
      tabindex="0"
      @click="handleClick"
      @keydown.esc="handleEscape"
      @keydown.enter="handleEnter"
      @keydown.left="handleArrow($event, 'x', left)"
      @keydown.right="handleArrow($event, 'x', right)"
      @keydown.up="handleArrow($event, 'y', up)"
      @keydown.down="handleArrow($event, 'y', down)"
      @blur="blurColor"
      @focus="focusColor"
  >
    <template v-for="(item, index) in list">
      <div
          :key="item + ':' + index"
          :class="[prefixCls + '-picker-colors-wrapper']">
        <div :data-color-id="index">
          <div
              :style="{background: item}"
              :class="[prefixCls + '-picker-colors-wrapper-color']"
          ></div>
          <div
              :ref="'color-circle-' + index"
              :class="[prefixCls + '-picker-colors-wrapper-circle', hideClass]"></div>
        </div>
      </div>
      <br v-if="lineBreak(list, index)"/>
    </template>
  </div>
</template>

<script>
import Emitter from '../../mixins/emitter'
import HandleEscapeMixin from './handleEscapeMixin'
import Prefixes from './prefixMixin'
import { clamp } from './utils'

export default {
  name: 'RecommendedColors',

  mixins: [Emitter, HandleEscapeMixin, Prefixes],

  props: {
    list: {
      type: Array,
      default: undefined
    }
  },

  data() {
    const columns = 12
    const rows = Math.ceil(this.list.length / columns)
    const normalStep = 1

    return {
      left: -normalStep,
      right: normalStep,
      up: -normalStep,
      down: normalStep,
      powerKey: 'shiftKey',
      grid: { x: 1, y: 1 },
      rows,
      columns
    }
  },
  computed: {
    hideClass() {
      return `${this.prefixCls}-hide`
    },
    linearIndex() {
      return this.getLinearIndex(this.grid)
    },
    currentCircle() {
      return this.$refs[`color-circle-${this.linearIndex}`][0]
    }
  },
  methods: {
    getLinearIndex(grid) {
      return this.columns * (grid.y - 1) + grid.x - 1
    },
    getMaxLimit(axis) {
      return axis === 'x' ? this.columns : this.rows
    },
    handleArrow(e, axis, direction) {
      e.preventDefault()
      e.stopPropagation()
      this.blurColor()
      const grid = { ...this.grid }
      if (e[this.powerKey]) {
        if (direction < 0) {
          grid[axis] = 1
        } else {
          grid[axis] = this.getMaxLimit(axis)
        }
      } else {
        grid[axis] += direction
      }

      const index = this.getLinearIndex(grid)

      if (index >= 0 && index < this.list.length) {
        this.grid[axis] = clamp(grid[axis], 1, this.getMaxLimit(axis))
      }

      this.focusColor()
    },
    blurColor() {
      this.currentCircle.classList.add(this.hideClass)
    },
    focusColor() {
      this.currentCircle.classList.remove(this.hideClass)
    },
    handleEnter(e) {
      this.handleClick(e, this.currentCircle)
    },
    handleClick(e, circle) {
      e.preventDefault()
      e.stopPropagation()

      this.$refs.reference.focus()

      const target = circle || e.target
      const colorId = target.dataset.colorId || target.parentElement.dataset.colorId

      if (colorId) {
        this.blurColor()
        const id = Number(colorId) + 1
        this.grid.x = id % this.columns || this.columns
        this.grid.y = Math.ceil(id / this.columns)
        this.focusColor()
        this.$emit('picker-color', this.list[colorId])
        this.$emit('change', { hex: this.list[colorId], source: 'hex' })
      }
    },
    lineBreak(list, index) {
      if (!index) {
        return false
      }

      const nextIndex = index + 1

      return nextIndex < list.length && nextIndex % this.columns === 0
    }
  }
}
</script>
